package middleware

import (
	"net/http"
	"strings"
)

// Handler 中间件处理接口
type Handler interface {
	ServeHTTP(http.ResponseWriter, *http.Request, func())
}

// HandlerFunc 中间件处理函数
type HandlerFunc func(http.ResponseWriter, *http.Request, func())

func (f HandlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request, next func()) {
	f(w, r, next)
}

// Constructor 中间件构造函数
type Constructor func(next Handler) Handler

// Chain 中间件链
type Chain struct {
	constructors []Constructor
}

// NewChain 创建新的中间件链
func NewChain(constructors ...Constructor) Chain {
	return Chain{
		append(([]Constructor)(nil), constructors...),
	}
}

// Then 将中间件链应用到http.Handler
func (c Chain) Then(h http.Handler) http.Handler {
	var final Handler = HandlerFunc(func(w http.ResponseWriter, r *http.Request, _ func()) {
		h.ServeHTTP(w, r)
	})

	for i := len(c.constructors) - 1; i >= 0; i-- {
		final = c.constructors[i](final)
	}

	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		final.ServeHTTP(w, r, nil)
	})
}

// Use 添加中间件到链中
func (c Chain) Use(constructors ...Constructor) Chain {
	newCons := make([]Constructor, len(c.constructors)+len(constructors))
	copy(newCons, c.constructors)
	copy(newCons[len(c.constructors):], constructors)

	return Chain{newCons}
}

// PathPrefix 路径前缀中间件
func PathPrefix(prefix string) Constructor {
	return func(next Handler) Handler {
		return HandlerFunc(func(w http.ResponseWriter, r *http.Request, proceed func()) {
			if strings.HasPrefix(r.URL.Path, prefix) {
				if proceed != nil {
					proceed()
				}
			} else {
				next.ServeHTTP(w, r, proceed)
			}
		})
	}
}

// Logger 日志中间件
func Logger() Constructor {
	return func(next Handler) Handler {
		return HandlerFunc(func(w http.ResponseWriter, r *http.Request, proceed func()) {
			// 记录请求开始
			// TODO: 添加详细的日志记录

			if proceed != nil {
				proceed()
			}

			// 记录请求结束
		})
	}
}

// Recover 恢复中间件
func Recover() Constructor {
	return func(next Handler) Handler {
		return HandlerFunc(func(w http.ResponseWriter, r *http.Request, proceed func()) {
			defer func() {
				if err := recover(); err != nil {
					http.Error(w, "Internal Server Error", http.StatusInternalServerError)
					// TODO: 添加错误日志记录
				}
			}()

			if proceed != nil {
				proceed()
			}
		})
	}
}
